package es.uma.scgt.dao.impl;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;

import es.uma.scgt.dao.TareaDao;
import es.uma.scgt.dto.GraficaPorFechaDto;
import es.uma.scgt.modelo.Fase;
import es.uma.scgt.modelo.Historico;
import es.uma.scgt.modelo.Peticion;
import es.uma.scgt.modelo.Tarea;
import es.uma.scgt.modelo.Usuario;

public class TareaDaoJpa implements TareaDao{
	@Autowired 
	private SessionFactory session;

	public List<Tarea> existeTareaPorPeticion(Integer pTrasnfT) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public void nuevaTarea(Tarea tmpTarea){
		session.getCurrentSession().saveOrUpdate(tmpTarea);
	}
	
	public Tarea encuentraTareaxId(Integer tareaId){
		
		return (Tarea)session.getCurrentSession().get(Tarea.class,tareaId);
	}
	
	public void eliminarTarea(Integer tareaId){
		
		Tarea t= encuentraTareaxId(tareaId);
		session.getCurrentSession().delete(t);
		
	}
	
	@SuppressWarnings("unchecked")
	public List<Tarea>getTareaMiEquipo(List<Usuario> listausuarioId){
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId)").setParameterList("listausuarioId", listausuarioId).list();
	}
	
	@SuppressWarnings("unchecked")
	public List<Tarea>getTareaPendienteMiEquipo(List<Usuario> listausuarioId){
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId) and t.fase ='"+Fase.PENDIENTE.toString()+"'").setParameterList("listausuarioId", listausuarioId).list();
	}
	
	@SuppressWarnings("unchecked")
	public List<Tarea>getTareaDesarrolloMiEquipo(List<Usuario> listausuarioId){
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId) and t.fase ='"+Fase.DESARROLLO.toString()+"'").setParameterList("listausuarioId", listausuarioId).list();
	}
	
	
	@SuppressWarnings("unchecked")
	public List<Tarea>getTareaTestMiEquipo(List<Usuario> listausuarioId){
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId) and t.fase ='"+Fase.TEST.toString()+"'").setParameterList("listausuarioId", listausuarioId).list();
	}
	
	//Finalizadas Mi Equipo
	@SuppressWarnings("unchecked")
	public List<Tarea>getTareaFinalizadaMiEquipo(List<Usuario> listausuarioId){
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId) and t.fase ='"+Fase.FINALIZADO.toString()+"'").setParameterList("listausuarioId", listausuarioId).list();
	}

	@SuppressWarnings("unchecked")
	public List<Tarea> getFechaFinHoy (List<Usuario> listausuarioId){
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId) and t.fechaFin = :hoy").setDate("hoy", new Date()).setParameterList("listausuarioId", listausuarioId).list();
	}
	
	@SuppressWarnings("unchecked")
	public List<Tarea> getTareaFinHoy (List<Usuario> listausuarioId){
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId) and t.fechaFin = :hoy and t.fase ='"+Fase.FINALIZADO.toString()+"'").setDate("hoy", new Date()).setParameterList("listausuarioId", listausuarioId).list();
	}
	
	@SuppressWarnings("unchecked")
	public List<Tarea> getTareaFinSemana (List<Usuario> listausuarioId){
		
		Date hoy = new Date();
		Calendar calendar = Calendar.getInstance();	
		calendar.setTime(hoy); // Configuramos la fecha que se recibe	
		calendar.add(Calendar.DAY_OF_YEAR, -7); 
		
		Date semana = calendar.getTime();
		
		
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId) and t.fechaFin >= :semana and t.fase ='"+Fase.FINALIZADO.toString()+"'").setDate("semana", semana).setParameterList("listausuarioId", listausuarioId).list();
	}
	
	
	
	
	@SuppressWarnings("unchecked")
	public Map<String,GraficaPorFechaDto> getTareaParaGrafica (List<Usuario> listausuarioId){
		Date hoy = new Date();
		Calendar calendar = Calendar.getInstance();	
		calendar.setTime(hoy); // Configuramos la fecha que se recibe	
		calendar.add(Calendar.DAY_OF_YEAR, -700); 
		
		Date semana = calendar.getTime();
		
		Session csession = session.getCurrentSession();
		Query query = csession.createQuery("select h.fechaModificacion, count(h.fase), h.fase from Historico h where h.usuarioModificacion in (:listausuarioId)"
				+ "group by date(h.fechaModificacion), h.fase having date(h.fechaModificacion) >= :semana");
		query.setDate("semana", semana).setParameterList("listausuarioId", listausuarioId);
		
		Map<String, GraficaPorFechaDto> resultado = new HashMap<String, GraficaPorFechaDto>();
		
		for (Iterator it = query.iterate(); it.hasNext();){
			Object[] row = (Object[]) it.next();
			GraficaPorFechaDto value = new GraficaPorFechaDto();
			Timestamp ts = (Timestamp) row[0];

			String fecha = new StringTokenizer(ts.toString(), " ").nextToken();
			StringTokenizer st = new StringTokenizer(fecha, "-");
			String ano = st.nextToken();
			String mes = st.nextToken();
			String dia = st.nextToken();
			fecha =  mes+ "/"+dia+"/"+ano;
			
			if (resultado.containsKey(fecha)){
				// si la fecha esta en el mapa
				value = resultado.get(fecha);
			}else{
				// si la fecha NO esta en el mapa, por lo que no tiene la propiedad fecha rellena dentro de value
				value.setDate(fecha);
			}
			Fase fase = (Fase) row[2];
			if ("FINALIZADO" == fase.name()){
				value.setF((Long) row[1]);
			}else if ("TEST" == fase.name()){
				value.setT((Long) row[1]);
			}else if ("DESARROLLO" == fase.name()){
				value.setD((Long) row[1]);
			}
			resultado.put(fecha, value);
		}
		
		
		return resultado;
	
	}
	
	@SuppressWarnings("unchecked")
	public List<Historico> getTareaTesSemana (List<Usuario> listausuarioId){
		Date hoy = new Date();
		Calendar calendar = Calendar.getInstance();	
		calendar.setTime(hoy); // Configuramos la fecha que se recibe	
		calendar.add(Calendar.DAY_OF_YEAR, -7); 
		
		Date semana = calendar.getTime();
		
		return session.getCurrentSession().createQuery("select h.fechaModificacion, count(h) from Historico h where h.usuarioModificacion in (:listausuarioId) and h.fase ='"+Fase.TEST.toString()+"' "
				+ "group by h.fechaModificacion having h.fechaModificacion >= :semana").setDate("semana", semana).setParameterList("listausuarioId", listausuarioId).list();
		
	}
	@SuppressWarnings("unchecked")
	public List<Historico> getTareaFinalSemana (List<Usuario> listausuarioId){
		Date hoy = new Date();
		Calendar calendar = Calendar.getInstance();	
		calendar.setTime(hoy); // Configuramos la fecha que se recibe	
		calendar.add(Calendar.DAY_OF_YEAR, -7); 
		
		Date semana = calendar.getTime();
		
		return session.getCurrentSession().createQuery("select h.fechaModificacion, count(h) from Historico h where h.usuarioModificacion in (:listausuarioId) and h.fase ='"+Fase.FINALIZADO.toString()+"' "
				+ "group by h.fechaModificacion having h.fechaModificacion >= :semana").setDate("semana", semana).setParameterList("listausuarioId", listausuarioId).list();
	
	}
	
	@SuppressWarnings("unchecked")
	public List<Tarea> getTareaEntreFechas (List<Usuario> listausuarioId, Date desde, Date hasta){
		
		return session.getCurrentSession().createQuery("select distinct t from Tarea t where t.usuario in (:listausuarioId) and t.fechaFin >= :desde and t.fechaFin <= :hasta and t.fase ='"+Fase.FINALIZADO.toString()+"'").setDate("desde", desde).setDate("hasta", hasta).setParameterList("listausuarioId", listausuarioId).list();
	}
	
	
	public Peticion hayPeticiondeTarea(Integer tareaId) {
		Tarea tarea = new Tarea();
		
		tarea = (Tarea)session.getCurrentSession().get(Tarea.class,tareaId);
		
		return tarea.getPeticion();
	}
	
	@SuppressWarnings("unchecked")
	public Integer contarTareasConPeticion (Integer peticionId){
		
	List<Tarea> listaTarea = new ArrayList<Tarea>();  

	Peticion peticion = new Peticion();
	peticion.setId(peticionId);
	listaTarea = session.getCurrentSession().createQuery("from Tarea t where t.peticion = :peticionId").setParameter("peticionId", peticion).list();
	
	return listaTarea.size();
	}
	
	@SuppressWarnings("unchecked")
	public Integer contarTareasFConPeticion (Integer peticionId){
		
		List<Tarea> listaTarea = new ArrayList<Tarea>();  

		Peticion peticion = new Peticion();
		peticion.setId(peticionId);
		listaTarea = session.getCurrentSession().createQuery("from Tarea t where t.peticion = :peticionId and t.fase ='"+Fase.FINALIZADO.toString()+"'").setParameter("peticionId", peticion).list();
		
		return listaTarea.size();
		}

	public Map<String, GraficaPorFechaDto> getTareaParaGraficaIntervalo(List<Usuario> listaUsuarios, Date fDesdeDate, Date fHastaDate) {
	
	
	Session csession = session.getCurrentSession();
	Query query = csession.createQuery("select h.fechaModificacion, count(h.fase), h.fase from Historico h where h.usuarioModificacion in (:listausuarioId)"
			+ "group by date(h.fechaModificacion), h.fase having date(h.fechaModificacion) >= :fDesdeDate and date(h.fechaModificacion)<= :fHastaDate order by h.fechaModificacion asc");
	query.setDate("fDesdeDate", fDesdeDate).setDate("fHastaDate",fHastaDate).setParameterList("listausuarioId", listaUsuarios);
	
	
	
	Map<String, GraficaPorFechaDto> resultado = new HashMap<String, GraficaPorFechaDto>();
	
	for (Iterator it = query.iterate(); it.hasNext();){
		Object[] row = (Object[]) it.next();
		GraficaPorFechaDto value = new GraficaPorFechaDto();
		Timestamp ts = (Timestamp) row[0];

		String fecha = new StringTokenizer(ts.toString(), " ").nextToken();
		StringTokenizer st = new StringTokenizer(fecha, "-");
		String ano = st.nextToken();
		String mes = st.nextToken();
		String dia = st.nextToken();
		fecha =  mes+ "/"+dia+"/"+ano;
		
		if (resultado.containsKey(fecha)){
			// si la fecha esta en el mapa
			value = resultado.get(fecha);
		}else{
			// si la fecha NO esta en el mapa, por lo que no tiene la propiedad fecha rellena dentro de value
			value.setDate(fecha);
		}
		Fase fase = (Fase) row[2];
		if ("FINALIZADO" == fase.name()){
			value.setF((Long) row[1]);
		}else if ("TEST" == fase.name()){
			value.setT((Long) row[1]);
		}else if ("DESARROLLO" == fase.name()){
			value.setD((Long) row[1]);
		}
		resultado.put(fecha, value);
	}
	
	
	return resultado;

	}

}
